#define pr_fmt(fmt)		"listTest:"fmt

#include <linux/module.h>
#include <linux/list.h>
#include <linux/slab.h>


#define LIST_TEST_INFO_SHOW
#ifdef LIST_TEST_INFO_SHOW
#define LIST_TEST_INFO(fmt,...) \
do{\
    pr_info( "%s,%d:"fmt"\n",__func__,__LINE__,##__VA_ARGS__);\
}while(0)
#else
#define LIST_TEST_INFO(fmt,...)
#endif


struct apple {
	struct list_head list;
	int id;
};

static LIST_HEAD(apple_top);

#define APPLE_STACK_MAX		10

#if 0
static 	void show_apple_stack()
{
	struct apple *it = NULL;

	list_for_each_entry(it, &apple_top, list) {
		if(it == NULL){
			LIST_TEST_INFO("it is NULL");
			continue;
		}
		LIST_TEST_INFO("apple->id:%d", it->id);
	}
}
#endif

static int __init list_test_drv_init()
{
	struct apple *tmp_apple = NULL;
	int count = 0;

	for( count = 0 ; count < APPLE_STACK_MAX; ++count) {

		tmp_apple = kzalloc(sizeof(struct apple), GFP_KERNEL);
		if(tmp_apple != NULL) {
			tmp_apple->id = count;
			list_add(&tmp_apple->list, &apple_top);
			LIST_TEST_INFO("push:apple->id:%d", tmp_apple->id);
			tmp_apple = NULL;
		}
	}

//	show_apple_stack();
	return 0;
}

static void __exit list_test_drv_exit()
{
	struct apple *it = NULL;

	while(!list_empty(&apple_top)) {
		it = list_first_entry(&apple_top, struct apple, list);
		if(it == NULL){
			LIST_TEST_INFO("it is NULL");
			continue;
		}
		LIST_TEST_INFO("pop:apple->id:%d", it->id);
		list_del(&it->list);
		kzfree(it);
		it = NULL;
	}
}

module_init(list_test_drv_init);
module_exit(list_test_drv_exit);
MODULE_AUTHOR("flagstaff Chen<flagstaff.chen@fake.com>");
MODULE_DESCRIPTION("Test the list API from kernel.");
MODULE_LICENSE("GPL v2");
